package dao

import (
	"inventory/internal/constant"
	"strconv"

	"context"
	"inventory/internal/model"
)

// FindAllMaterialTypes  查询所有的物料类别
func (d *Dao) FindAllMaterialTypes(ctx context.Context, sgID, storeID uint32) (materialTypes []*model.MaterialType, err error) {
	err = d.TransContext(ctx).Model(&model.MaterialType{}).Where("sg_id = ? and p_store_id = ? and status = ?",
		sgID, storeID, constant.MaterialTypeValid).Find(&materialTypes).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}

// FindMaterialTypeByIDs  根据ID查询所有的物料类别
func (d *Dao) FindMaterialTypeByIDs(ctx context.Context, sgID uint32, IDs []uint32) (materialTypes []*model.MaterialType, err error) {
	err = d.TransContext(ctx).Model(&model.MaterialType{}).Where("sg_id = ? and id in ? and status = ?",
		sgID, IDs, constant.MaterialTypeValid).Find(&materialTypes).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}

// FindMaterialTypeByParentID  根据ID查询所有的子物料类别
func (d *Dao) FindMaterialTypeByParentID(ctx context.Context, sgID uint32, parentID uint32) (materialTypes []*model.MaterialType, err error) {
	err = d.TransContext(ctx).Model(&model.MaterialType{}).Where("sg_id = ? and parent_id = ? and status = ?",
		sgID, parentID, constant.MaterialTypeValid).Find(&materialTypes).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}

// AddMaterialType 新增产品配置类别
func (d *Dao) AddMaterialType(ctx context.Context, materialType *model.MaterialType) (err error) {
	err = d.TransContext(ctx).Create(materialType).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}

// UpdateMaterialType 编辑产品配置类别
func (d *Dao) UpdateMaterialType(ctx context.Context, materialType *model.MaterialType) (err error) {
	err = d.TransContext(ctx).Model(materialType).Updates(*materialType).Error
	err = d.processSqlError(err)
	return
}

// DeleteMaterialType 删除产品配置类别
func (d *Dao) DeleteMaterialType(ctx context.Context, sgID, storeID, empID, ID uint32) (err error) {
	err = d.TransContext(ctx).Model(&model.MaterialType{}).Where(
		"sg_id = ? and p_store_id = ? and id = ?", sgID, storeID, ID).Updates(map[string]interface{}{
		"status":   nil,
		"operator": empID,
	}).Error
	err = d.processSqlError(err)
	return
}

// GetMaterialType 获取产品配置类别
func (d *Dao) GetMaterialType(ctx context.Context, sgID, storeID, ID uint32) (materialType *model.MaterialType, err error) {
	materialType = &model.MaterialType{}
	err = d.TransContext(ctx).Where("sg_id = ? and p_store_id = ? and id = ? and status = ?",
		sgID, storeID, ID, constant.MaterialTypeValid).Take(materialType).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}

// CheckExistMaterialTypeName 检查名称重复
func (d *Dao) CheckExistMaterialTypeName(ctx context.Context, sgID, storeID, parentID uint32, name string) (isExist bool, err error) {
	var count int64
	err = d.TransContext(ctx).Model(&model.MaterialType{}).Where(
		"sg_id = ? and p_store_id = ? and parent_id = ? and name = ? and status = ?",
		sgID, storeID, parentID, name, constant.MaterialTypeValid).Count(&count).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return count >= 1, err
}

// GenerateMaterialTypeCode 生成code
func (d *Dao) GenerateMaterialTypeCode(ctx context.Context, sgID, storeID, parentID uint32) (code string, err error) {
	var count int64
	count, err = d.Count(ctx, &model.MaterialType{}, map[string]interface{}{
		"sg_id":      sgID,
		"p_store_id": storeID,
		"parent_id":  parentID,
	})
	if err != nil {
		err = d.processSqlError(err)
	}
	return strconv.Itoa(int(count) + 1), err
}

// GenerateMaterialCode 生成code
func (d *Dao) GenerateMaterialCode(ctx context.Context, sgID, storeID, mtID uint32) (code string, err error) {
	var count int64
	count, err = d.Count(ctx, &model.Material{}, map[string]interface{}{
		"sg_id":      sgID,
		"p_store_id": storeID,
		"mt_id":      mtID,
	})
	if err != nil {
		err = d.processSqlError(err)
	}
	return strconv.Itoa(int(count) + 1), err
}

// CheckExistChildMaterialType 检查是否存在子类目
func (d *Dao) CheckExistChildMaterialType(ctx context.Context, sgID, storeID, ID uint32) (isExist bool, err error) {
	var count int64
	err = d.TransContext(ctx).Model(&model.MaterialType{}).Where(
		"sg_id = ? and p_store_id = ? and parent_id = ? and status = ?",
		sgID, storeID, ID, constant.MaterialTypeValid).Count(&count).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return count >= 1, err
}

// CheckExistChildMaterial 检查是否存在子物料
func (d *Dao) CheckExistChildMaterial(ctx context.Context, sgID, storeID, ID uint32) (isExist bool, err error) {
	var count int64
	err = d.TransContext(ctx).Model(&model.Material{}).Where(
		"sg_id = ? and p_store_id = ? and mt_id = ? and status = ?",
		sgID, storeID, ID, constant.MaterialValid).Count(&count).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return count >= 1, err
}

// CheckExistMaterialUnit 检查单位是否存在
func (d *Dao) CheckExistMaterialUnit(ctx context.Context, sgID, storeID, unitID uint32) (isExist bool, err error) {
	var count int64
	err = d.TransContext(ctx).Model(&model.Material{}).Where(
		"sg_id = ? and p_store_id = ? and status = ? and (unit = ? or purchase_unit = ？ or storage_unit = ?)",
		sgID, storeID, constant.MaterialValid, unitID, unitID, unitID).Count(&count).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return count >= 1, err
}

// FindMaterialsByTypes 根据类型查询物料列表
func (d *Dao) FindMaterialsByTypes(ctx context.Context, sgID, storeID uint32, MaterialTypeIDs []uint32) (
	materials []*model.Material, err error) {
	err = d.TransContext(ctx).Model(&model.Material{}).Where(
		"sg_id = ? and p_store_id = ? and mt_id in ? and status = ?",
		sgID, storeID, MaterialTypeIDs, constant.MaterialValid).Find(&materials).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}

// FindMaterialsByIDs 根据物料IDs查询列表
func (d *Dao) FindMaterialsByIDs(ctx context.Context, materialIDs []uint64) (materials []*model.Material, err error) {
	err = d.TransContext(ctx).Model(&model.Material{}).Where(
		"id in ? and status = ?", materialIDs, constant.MaterialValid).Find(&materials).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}

// GetMaterial 获取指定物料
func (d *Dao) GetMaterial(ctx context.Context, sgID, storeID uint32, ID uint64) (material *model.Material, err error) {
	material = &model.Material{}
	err = d.TransContext(ctx).Where("sg_id = ? and p_store_id = ? and id = ? and status = ?",
		sgID, storeID, ID, constant.MaterialValid).Take(material).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}

// FindUnitsByIDs 获取指定单位列表
func (d *Dao) FindUnitsByIDs(ctx context.Context, sgID, storeID uint32, ids []uint32) (units []*model.Unit, err error) {
	err = d.TransContext(ctx).Model(&model.Unit{}).Where(
		"sg_id = ? and p_store_id = ? and id in ? and status = ?", sgID, storeID, ids, constant.UnitValid).Find(&units).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}

// GetUnitByName 基于名称获取单位
func (d *Dao) GetUnitByName(ctx context.Context, sgID, storeID uint32, name string) (unit *model.Unit, err error) {
	unit = &model.Unit{}
	err = d.TransContext(ctx).Model(&model.Unit{}).Where(
		"sg_id = ? and p_store_id = ? and name = ? and status = ?",
		sgID, storeID, name, constant.UnitValid).Take(unit).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}

// FindUnitsByIDsCompatible 获取指定单位列表 兼容历史脏数据
func (d *Dao) FindUnitsByIDsCompatible(ctx context.Context, sgID uint32, ids []uint32) (units []*model.Unit, err error) {
	err = d.TransContext(ctx).Model(&model.Unit{}).Where(
		"sg_id = ?  and id in ? and status = ?", sgID, ids, constant.UnitValid).Find(&units).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}

// FindUnits 获取所有单位列表
func (d *Dao) FindUnits(ctx context.Context, sgID, pStoreID uint32) (units []*model.Unit, err error) {
	err = d.TransContext(ctx).Model(&model.Unit{}).Where(
		"sg_id = ? and p_store_id = ? and status = ?", sgID, pStoreID, constant.UnitValid).Find(&units).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}

// FindMaterialsByPage 分页获取物料
func (d *Dao) FindMaterialsByPage(ctx context.Context, sgID, pStoreID, fetchStoreID uint32, fetchMode, pageNo, pageSize int,
	query string) (
	total int64, materials []*model.Material, err error) {
	db := d.TransContext(ctx).Model(&model.Material{}).Where(
		"sg_id = ? and status = ?", sgID, constant.MaterialValid)
	if fetchMode == constant.FetchModeFollowPStoreID {
		db = db.Where("p_store_id = ?", fetchStoreID)
	} else if pStoreID == 0 {
		db = db.Where("p_store_id = ?", pStoreID)
	} else {
		db = db.Where("p_store_id in ?", []uint32{0, pStoreID})
	}
	if query != "" {
		queryKey := "%" + query + "%"
		db = db.Where("(name like ? or code like ?)", queryKey, queryKey)
	}
	if err = db.Count(&total).Error; err != nil {
		err = d.processSqlError(err)
		return
	}
	err = db.Order("id asc").Offset((pageNo - 1) * pageSize).Limit(pageSize).Find(&materials).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}
